package service

import (
	"context"
	"database/sql"
	"fmt"
	"strings"
)

// SQLExecutor SQL执行器
type SQLExecutor struct {
	db *sql.DB
}

// NewSQLExecutor 创建SQL执行器
func NewSQLExecutor(db *sql.DB) *SQLExecutor {
	return &SQLExecutor{
		db: db,
	}
}

// Execute 执行SQL语句
func (e *SQLExecutor) Execute(ctx context.Context, sqlContent string, params map[string]interface{}) (interface{}, error) {
	// 解析SQL语句中的参数
	query, args, err := e.parseSQL(sqlContent, params)
	if err != nil {
		return nil, err
	}

	// 执行SQL查询
	rows, err := e.db.QueryContext(ctx, query, args...)
	if err != nil {
		return nil, fmt.Errorf("执行SQL失败: %v", err)
	}
	defer rows.Close()

	// 获取列信息
	columns, err := rows.Columns()
	if err != nil {
		return nil, fmt.Errorf("获取列信息失败: %v", err)
	}

	// 准备结果集
	var result []map[string]interface{}
	for rows.Next() {
		// 创建一行数据
		row := make(map[string]interface{})
		values := make([]interface{}, len(columns))
		valuePtrs := make([]interface{}, len(columns))
		for i := range columns {
			valuePtrs[i] = &values[i]
		}

		// 扫描行数据
		if err := rows.Scan(valuePtrs...); err != nil {
			return nil, fmt.Errorf("扫描行数据失败: %v", err)
		}

		// 将数据转换为map
		for i, col := range columns {
			var v interface{}
			val := values[i]
			b, ok := val.([]byte)
			if ok {
				v = string(b)
			} else {
				v = val
			}
			row[col] = v
		}
		result = append(result, row)
	}

	if err := rows.Err(); err != nil {
		return nil, fmt.Errorf("遍历结果集失败: %v", err)
	}

	return result, nil
}

// parseSQL 解析SQL语句和参数
func (e *SQLExecutor) parseSQL(sqlContent string, params map[string]interface{}) (string, []interface{}, error) {
	// 替换SQL中的参数占位符
	query := sqlContent
	var args []interface{}
	var i int

	for k, v := range params {
		placeholder := fmt.Sprintf(":%s", k)
		if !strings.Contains(query, placeholder) {
			continue
		}

		// 处理数组参数
		if arr, ok := v.([]interface{}); ok {
			placeholders := make([]string, len(arr))
			for j := range arr {
				i++
				placeholders[j] = fmt.Sprintf("$%d", i)
				args = append(args, arr[j])
			}
			query = strings.Replace(query, placeholder, strings.Join(placeholders, ","), -1)
		} else {
			i++
			query = strings.Replace(query, placeholder, fmt.Sprintf("$%d", i), -1)
			args = append(args, v)
		}
	}

	return query, args, nil
}
